package com.qh.yyxt.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qh.yyxt.mapper.*;
import com.qh.yyxt.pojo.entity.thing.*;
import com.qh.yyxt.pojo.vo.ActVO;
import com.qh.yyxt.pojo.vo.ActivityVO;
import com.qh.yyxt.pojo.vo.BringOrBackVO;
import com.qh.yyxt.service.ActivityService;
import com.qh.yyxt.service.BackService;
import com.qh.yyxt.service.BringService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
@Slf4j
public class ActivityServiceImpl extends ServiceImpl<ActivityMapper, Activity> implements ActivityService {

    @Autowired
    private LendMapper lendMapper;
    @Autowired
    private ThingSizeMapper sizeMapper;
    @Autowired
    private ThingMapper thingMapper;
    @Autowired
    private BringMapper bringMapper;
    @Autowired
    private BackMapper backMapper;
    @Autowired
    private BackService backService;
    @Autowired
    private BringService bringService;
    @Autowired
    private ThingSizeMapper thingSizeMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String insertActivity(ActivityVO activityVO, int[] tid, int[] sid, int[] num) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String startTime = dateTimeFormatter.format(activityVO.getStartTime());
        String endTime = dateTimeFormatter.format(activityVO.getEndTime());
//        log.info("检验收取到的时间格式是否正确"+activityVO.getStartTime().toString());
        String flag = isEnoughBySelect(startTime, endTime, tid, sid, num);
        if (flag!=null&&!"".equals(flag)){
            return flag;
        }
        Boolean b = false;
        //组装要存储的Activity
        Activity activity = new Activity();
        BeanUtils.copyProperties(activityVO,activity);
        activity.setApplyTime(dateTimeFormatter.format(LocalDateTime.now()));
        activity.setStartTime(startTime);
        activity.setEndTime(endTime);
        activity.setAprStatus("待审批");
        activity.setLendStatus("未借出");
        baseMapper.insert(activity);

        //组装套存储的lend
        Lend lend = null;
        for(int i=0;i<tid.length;i++){
            if(num[i]==0) continue;
            lend = new Lend();
            lend.setAid(activity.getId());
            lend.setTid(tid[i]);
            lend.setSid(sid[i]);
            lend.setNum(num[i]);
            lend.setName(thingMapper.selectById(tid[i]).getName());
            QueryWrapper<ThingSize> thingSizeQueryWrapper = new QueryWrapper<>();
            thingSizeQueryWrapper.select("size").eq("id",sid[i]);
            lend.setSize((String) sizeMapper.selectObjs(thingSizeQueryWrapper).get(0));
            lendMapper.insert(lend);
        }
        return "申请成功，注意查看申请状态！";
    }

    private String isEnoughBySelect(String startTime, String endTime, int[] tid, int[] sid, int[] num){

        //组装需要的Map
        Map<Integer,Integer> map = new LinkedHashMap<>();
        for (int i=0;i<tid.length;i++){
            if(!map.containsKey(sid[i])){
                map.put(sid[i],num[i]);
            }else {
                Integer n = map.get(sid[i])+num[i];
                map.put(sid[i],n);
            }
        }
        ArrayList<Integer> sidList = new ArrayList<>();
        for (int s:sid){
            sidList.add(s);
        }
        //组装总数map
        List<ThingSize> thingSizes = thingSizeMapper.selectBatchIds(sidList);
        Map<Integer,Integer> sMap = new HashMap<>();
        for(ThingSize ts :thingSizes){
            if(!sMap.containsKey(ts.getId())){
                sMap.put(ts.getId(),ts.getRenum());
            }else {
                Integer n = sMap.get(ts.getId())+ts.getRenum();
                sMap.put(ts.getId(),n);
            }
        }

        QueryWrapper<Activity> activityQueryWrapper = new QueryWrapper<>();
        activityQueryWrapper.ne("apr_status","已归还")
                .and(i->{
                    i.ge("end_time",startTime).le("start_time",startTime)
                    .or()
                    .ge("end_time",endTime).le("start_time",endTime);
                });
        List<Activity> activities = baseMapper.selectList(activityQueryWrapper);
        List<Lend> lends = new ArrayList<>();
        activities.forEach(act->{
            QueryWrapper<Lend> lendQueryWrapper = new QueryWrapper<>();
            lendQueryWrapper.eq("aid",act.getId());
            lends.addAll(lendMapper.selectList(lendQueryWrapper));
        });

        for(Lend lend:lends){
            if(!sMap.containsKey(lend.getSid())) continue;
            int nu = sMap.get(lend.getSid())-lend.getNum();
            sMap.put(lend.getSid(),nu);
        }
        boolean flag = false;
        StringBuffer stringBuffer = new StringBuffer();
        for(Map.Entry<Integer,Integer> entry:map.entrySet()){
            Integer key = entry.getKey();
            Integer value = entry.getValue();
            if(sMap.get(key)<value){
                ThingSize thingSize = thingSizeMapper.selectById(key);
                stringBuffer.append(thingMapper.selectById(thingSize.getTid()).getName()+"的"+thingSize.getSize()+"库存数量不足，当前库存数为："+sMap.get(key));
                stringBuffer.append(" \n ");
                flag=true;
            }
        }
        if(flag) return stringBuffer.toString();
        return null;
    }

    @Override
    public ActVO getActById(Long id) {
        Activity activity = baseMapper.selectById(id);
        QueryWrapper<Lend> lendWrapper = new QueryWrapper<>();
        lendWrapper.eq("aid",id);
        List<Lend> lends = lendMapper.selectList(lendWrapper);
        Bring bring = bringMapper.selectOne(new QueryWrapper<Bring>().eq("aid",id));
        Back back = backMapper.selectOne(new QueryWrapper<Back>().eq("aid",id));
        return new ActVO(activity,lends,bring,back);
    }

    @Override
    public boolean setAprStatus(Long aid, String approver, String status) {
        Activity activity = baseMapper.selectById(aid);
        if (activity==null) return false;
        activity.setApprover(approver);
        activity.setAprStatus(status);
        int n = baseMapper.updateById(activity);
        return n>0;
    }

    /**
     * 审批通过
     * @param aid
     * @param approver
     * @param status
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean approval(Long aid, String approver, String status) {
        List<Lend> lends = lendMapper.selectList(new QueryWrapper<Lend>().eq("aid",aid));

//        if(isEnough(lends) && updateThings(lends)){
        Activity activity = baseMapper.selectById(aid);
        activity.setApprover(approver);
        activity.setAprStatus(status);
        activity.setLendStatus("未借出");
        int i = baseMapper.updateById(activity);
        return true;

    }

    private boolean isEnough(List<Lend> lends){
        for(Lend lend:lends){
            Integer num = sizeMapper.selectById(lend.getSid()).getRenum();
            if (lend.getNum()>num) return false;
        }
        return true;
    }
    private boolean updateThings(List<Lend> lends){
        Map<Integer,Integer> map = new HashMap<>();
        for(Lend lend:lends){
            int id = lend.getTid();
            int num = lend.getNum();
            if(map.containsKey(id)){
                num = num + map.get(id);
            }
            map.put(id,num);
            ThingSize thingSize = sizeMapper.selectById(lend.getSid());
            thingSize.setRenum(thingSize.getRenum()-lend.getNum());
            sizeMapper.update(thingSize);
        }
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            Thing thing = thingMapper.findById(entry.getKey());
            log.info(entry.getKey()+" "+entry.getValue());
            thing.setRenum(thing.getRenum() - entry.getValue());
            thingMapper.updateById(thing);
        }
        return true;
    }

    @Override
    public String outStock(BringOrBackVO bringOrBackVO) {
        String signs = bringOrBackVO.getSigns();
        if(signs==null || signs.equalsIgnoreCase(""))
            return "请输入出库物品编号！";
        List<String> signList = Arrays.asList(signs.split(" |\\r?\\n"));
        QueryWrapper<Lend> lendQueryWrapper = new QueryWrapper<>();
        lendQueryWrapper
                .select("SUM(num)")
                .eq("aid", bringOrBackVO.getAid())
                .groupBy("aid");
        Integer sum = Integer.parseInt(lendMapper.selectObjs(lendQueryWrapper).get(0).toString());
        if (sum>signList.size()){
            return "物品编号数量不足！借用物品数为"+sum+" 物品编号数为"+signList.size();
        }else if(sum<signList.size()){
            return "物品编号数大于物品借用数！";
        }
        Bring bring = bringMapper.selectOne(new QueryWrapper<Bring>().eq("aid",bringOrBackVO.getAid()));
        if(bring==null) {
            bring = new Bring();
        }
        BeanUtils.copyProperties(bringOrBackVO,bring);
        bring.setBName(bringOrBackVO.getName());
        bringService.saveOrUpdate(bring);
        Activity activity = baseMapper.selectById(bringOrBackVO.getAid());
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        activity.setPassTime(dateTimeFormatter.format(LocalDateTime.now()));
        activity.setLendStatus("已借出");
        StringBuffer stringBuffer = new StringBuffer("");
        signList.forEach(s->{
            if (s!=null||!s.equals(""))
                stringBuffer.append(s+" ");
        });
        activity.setAllThings(stringBuffer.toString());
        activity.setUnReturnThings(stringBuffer.toString());
        int result = baseMapper.updateById(activity);
        return result>0?"出库成功！":"操作失败，请稍后重试！";
    }

    @Override
    public String inStock(BringOrBackVO bringOrBackVO) {
        String signs = bringOrBackVO.getSigns();
        if(signs==null || signs.equals(""))
            return "请输入入库物品编号！";
        Back back = backMapper.selectOne(new QueryWrapper<Back>().eq("aid",bringOrBackVO.getAid()));
        if(back==null) {
            back = new Back();
        }
        BeanUtils.copyProperties(bringOrBackVO,back);
        back.setRName(bringOrBackVO.getName());
        backService.saveOrUpdate(back);

        Activity activity = baseMapper.selectById(bringOrBackVO.getAid());
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        activity.setPassTime(dateTimeFormatter.format(LocalDateTime.now()));
        String allThings = activity.getAllThings();
        String unReturnThings = activity.getUnReturnThings();
        List<String> allList = null;
        List<String> unList = null;
        List<String> returnList = Arrays.asList(signs.split(" |\\r?\\n"));
        returnList.remove("");

        returnList.sort(Comparator.comparing(String::hashCode));
        if(allThings==null||allThings.equals("")||unReturnThings==null||unReturnThings.equals("")){
            activity.setLendStatus("已归还");
            activity.setUnReturnThings("");
            activity.setReturnedThings(activity.getAllThings());
            baseMapper.updateById(activity);
            return "物品已全部归还！";
        }

        allList = Arrays.asList(allThings.split(" |\\r?\\n"));
        allList.remove("");
        allList.sort(Comparator.comparing(String::hashCode));
        unList = Arrays.asList(unReturnThings.split(" |\\r?\\n"));
        unList.remove("");
        unList.sort(Comparator.comparing(String::hashCode));

        if(unList.containsAll(returnList)){
            HashSet<String> h1 = new HashSet<>(unList);
            HashSet<String> h2 = new HashSet<>(returnList);
            h1.removeAll(h2);
            unList = new ArrayList<>(h1);
            if (unList.isEmpty()){
                activity.setLendStatus("已归还");
                activity.setUnReturnThings("");
                activity.setReturnedThings(activity.getAllThings());
                baseMapper.updateById(activity);
//                returnAll(activity.getId());
                return "物品已全部归还！";
            }
            StringBuilder stringBuilder = new StringBuilder("");
            for(String s: returnList){
                stringBuilder.append(s).append(" ");
            }
            String rt = stringBuilder.toString();
            if(!rt.equals("")){
                rt = rt.substring(0,rt.length()-1);
            }
            //rt为本次输入的编号，加到已归还这里
            String returnedThings = activity.getReturnedThings();
            if(returnedThings!=null&&!returnedThings.equals(" ")){
                activity.setReturnedThings(activity.getReturnedThings()+" "+rt);
            }else {
                activity.setReturnedThings(rt);
            }
            activity.setLendStatus("部分归还");
            stringBuilder = new StringBuilder("");
            for(String s:unList){
                stringBuilder.append(s).append(" ");
            }
            rt = stringBuilder.toString();
            if(!rt.equals("")){
                rt = rt.substring(0,rt.length()-1);
            }
//            此时rt为未归还编号
            activity.setUnReturnThings(rt);
            baseMapper.updateById(activity);
            return "操作成功！";
        }else {
            return "物品编号存在错误！";
        }
    }
    private void returnAll(Long aid){
        List<Lend> lends = lendMapper.selectList(new QueryWrapper<Lend>().eq("aid",aid));
        Map<Integer,Integer> map = new HashMap<>();
        for(Lend lend:lends){
            int id = lend.getTid();
            int num = lend.getNum();
            if(map.containsKey(id)){
                num = num + map.get(id);
            }
            map.put(id,num);
            ThingSize thingSize = sizeMapper.selectById(lend.getSid());
            thingSize.setRenum(thingSize.getRenum()+lend.getNum());
            sizeMapper.update(thingSize);
        }
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            Thing thing = thingMapper.findById(entry.getKey());
            log.info(entry.getKey()+" "+entry.getValue());
            thing.setRenum(thing.getRenum() + entry.getValue());
            thingMapper.updateById(thing);
        }
    }
}
